﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Display = System.Timers;

namespace DirectoryTree_Scanning
{
    class Program
    {
        #region declarations
        static long _lngFileCount = 0;
        static long _lngDirCount = 0;
        static long _lngTreeSize = 0;

        static System.Timers.Timer _tmrThreadState;

        static DirectorySync _ds;

        //constants
        static int AREA_RESULT_TOP = 10;
        static int AREA_RESULT_LEFT = 17;
        #endregion



        #region main
        static void Main(string[] args)
        {
            //prepare display timer
            _tmrThreadState = new System.Timers.Timer(500);
            _tmrThreadState.Elapsed += _tmrThreadState_Elapsed;
            _tmrThreadState.Start();

            //generate config object
            ScanDirectoryConfig sdc = new ScanDirectoryConfig();

            //create DirectorySync object and it's event subscriptions
            _ds = new DirectorySync();

            _ds.BeforeProcessing += _ds_BeforeProcessing;
            _ds.AfterProcessing += _ds_AfterProcessing;
            _ds.ProcessingFile += ds_ProcessingFile;
            _ds.ProcessingDirectory += ds_ProcessingDirectory;


            bool fBreak = false;
            while (!fBreak)
            {
                Console.Clear();
                _printMenu();

                ConsoleKeyInfo cki = Console.ReadKey();
                switch (cki.Key)
                {
                    case ConsoleKey.X:
                        fBreak = true;
                        break;

                    case ConsoleKey.Escape:
                        _ds.Halt = true;
                        break;

                    case ConsoleKey.S:
                        sdc.ScanPath = @"G:\";
                        sdc.Type = ScanDirectoryTypes.Count;
                        _ds.ScanDirectoryTreeAsync(sdc);
                        break;

                    case ConsoleKey.F:
                        sdc.ScanPath = @"G:\";
                        sdc.Type = ScanDirectoryTypes.Count | ScanDirectoryTypes.SumFileSize;
                        _ds.ScanDirectoryTreeAsync(sdc);
                        break;
                }
            }

            //shutdown
            _tmrThreadState.Stop();

            _ds.BeforeProcessing -= _ds_BeforeProcessing;
            _ds.AfterProcessing -= _ds_AfterProcessing;
            _ds.ProcessingFile -= ds_ProcessingFile;
            _ds.ProcessingDirectory -= ds_ProcessingDirectory;

            _ds = null;
        }
        #endregion



        #region event handling
        static void _ds_AfterProcessing(object sender)
        {
        }

        static void _ds_BeforeProcessing(object sender)
        {
            _lngFileCount = 0;
            _lngDirCount = 0;
            _lngTreeSize = 0;
        }

        static void ds_ProcessingDirectory(object sender, ProcessingDirectoryEventArgs e)
        {
            _lngDirCount++;
        }

        static void ds_ProcessingFile(object sender, ProcessingFileEventArgs e)
        {
            _lngFileCount++;
            _lngTreeSize += e.FileSize;
        }

        static void _tmrThreadState_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            //display everything
            _displayDirectoryProgress();
            _displayFileProgress();
            _displayThreadState();
        }
        #endregion



        #region display
        static void _printMenu()
        {
            //Directory count: #######
            //File count     : #######
            Console.SetCursorPosition(0, AREA_RESULT_TOP);
            Console.WriteLine("Directory count:");
            Console.WriteLine("File count     :");
            Console.WriteLine("Treesize       :");
            Console.WriteLine("ThreadState    :");
            Console.WriteLine("Thread Halt    :");

            //print menu
            Console.SetCursorPosition(0, 0);
            Console.WriteLine("Directory Tree Scanner");
            Console.WriteLine("");
            Console.WriteLine("s - Start scan progress");
            Console.WriteLine("f - Start scan progress including file size");
            Console.WriteLine("ESC - Stop scan progress");
            Console.WriteLine("x - End program");
        }

        static void _displayDirectoryProgress()
        {
            //remember cursor position
            int l = Console.CursorLeft;
            int t = Console.CursorTop;

            //0123456789012345678901234567890
            //Directory count: #######
            //File count     : #######
            Console.SetCursorPosition(AREA_RESULT_LEFT, AREA_RESULT_TOP);
            Console.Write(_lngDirCount);
            Console.Write("          ");

            //set cursor back
            Console.SetCursorPosition(l, t);
        }

        static void _displayFileProgress()
        {
            //remember cursor position
            int l = Console.CursorLeft;
            int t = Console.CursorTop;

            //0123456789012345678901234567890
            //Directory count: #######
            //File count     : #######
            Console.SetCursorPosition(AREA_RESULT_LEFT, AREA_RESULT_TOP + 1);
            Console.Write(_lngFileCount);
            Console.Write("          ");
            Console.SetCursorPosition(AREA_RESULT_LEFT, AREA_RESULT_TOP + 2);
            Console.Write(_lngTreeSize.ToString("##,0"));
            Console.Write("          ");

            //set cursor back
            Console.SetCursorPosition(l, t);
        }

        static void _displayThreadState()
        {
            //break condition
            if (_ds.ScanThread == null) { return; }

            //remember cursor position
            int l = Console.CursorLeft;
            int t = Console.CursorTop;

            Console.SetCursorPosition(AREA_RESULT_LEFT, AREA_RESULT_TOP + 3);
            Console.Write(_ds.ScanThread.ThreadState.ToString());
            Console.Write("          ");
            Console.SetCursorPosition(AREA_RESULT_LEFT, AREA_RESULT_TOP + 4);
            Console.Write(_ds.Halt.ToString());
            Console.Write("          ");

            //set cursor back
            Console.SetCursorPosition(l, t);
        }
        #endregion
    }
}
